@dataknut)If you wish to refer to any of the material from this report please cite as:
Report circulation:
This work is (c) 2020 the University of Southampton.
I usually do energy demand research but in the absence of access to real time demand data on lockdown (unlike during the World Cup) I’m looking at other things.
Data for Southampton downloaded from :
Southampton City Council collects various forms of air quality data at the sites shown in 2.1. Some of these sites feed data to AURN. The data that goes to AURN is then ratifified to check for outliers and instrument/measurement error. AURN data less than six months old has not undergone this process. Given that we are interested in very recent patterns, we do not use the AURN data.
Data health warning: The southampton.my-air.uk data used is not ratified. Results here should therefore be considered preliminary.
For much more detailed analysis see a longer and very messy data report.
sotonAirDT <- sotonAirDT[source == "southampton.my-air.uk"]
sotonAirDT[, `:=`(obsDate, lubridate::date(dateTimeUTC))]
# this is such a kludge
sotonAirDT[, `:=`(dateDecimal, lubridate::decimal_date(obsDate))]
sotonAirDT[, `:=`(year, lubridate::year(obsDate))]
sotonAirDT[, `:=`(dayOfYear, lubridate::as_date(lubridate::date_decimal(2020 + (dateDecimal - year))))] # sets 'year' portion to 2020 so the lockdown annotation works
sotonAirDT[, `:=`(compareYear, ifelse(year == 2020, "2020", "2016-2019"))]
sotonAirDT[, `:=`(site, ifelse(site == "Southampton A33", "Southampton A33 (via AURN)", site))]
sotonAirDT[, `:=`(site, ifelse(site == "Southampton Centre", "Southampton Centre (via AURN)", site))]
t <- sotonAirDT[!is.na(value), .(nObs = .N, nPollutants = uniqueN(pollutant)), keyby = .(site, source)]
kableExtra::kable(t, caption = "Sites, data source and number of valid observations", digits = 2) %>%
kable_styling()
| site | source | nObs | nPollutants |
|---|---|---|---|
| Southampton - A33 Roadside (near docks, AURN site) | southampton.my-air.uk | 69612 | 2 |
| Southampton - Background (near city centre, AURN site) | southampton.my-air.uk | 165845 | 6 |
| Southampton - Onslow Road (near RSH) | southampton.my-air.uk | 71398 | 2 |
| Southampton - Victoria Road (Woolston) | southampton.my-air.uk | 55066 | 2 |
yLab <- "Nitrogen Dioxide (ug/m3)"
no2dt <- sotonAirDT[pollutant == "no2"]
Figure 3.1 shows the most recent hourly data.
recentDT <- no2dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)
p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90,
hjust = 1)) + labs(caption = paste0(myParams$lockdownCap, myParams$weekendCap))
# final plot - adds annotations
yMin <- min(recentDT$value)
yMax <- max(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
Figure 3.1: Nitrogen Dioxide levels, Southampton (hourly, recent)
Figure 3.2 shows the most recent mean daily values compared to previous years.
plotDT <- no2dt[!is.na(value) & dayOfYear <= lubridate::today(), .(mean = mean(value)), keyby = .(dayOfYear,
compareYear)]
# final plot - adds annotations
yMin <- min(plotDT$mean)
yMax <- max(plotDT$mean)
p <- compareYearsPlot(plotDT)
p <- addLockdownDate(p)
addWeekendsDate(p)
Figure 3.2: Nitrogen Dioxide levels, Southampton (daily mean)
Beware seasonal trends and weather effects
yLab <- "Oxides of Nitrogen (ug/m3)"
noxdt <- sotonAirDT[pollutant == "nox"]
Figure 4.1 shows the most recent hourly data.
recentDT <- noxdt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)
p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90,
hjust = 1)) + labs(caption = paste0(myParams$lockdownCap, myParams$weekendCap))
# final plot - adds annotations
yMin <- min(recentDT$value)
yMax <- max(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
Figure 4.1: Oxides of nitrogen levels, Southampton (hourly, recent)
Figure 4.2 shows the most recent mean daily values compared to previous years.
plotDT <- noxdt[!is.na(value) & dayOfYear <= lubridate::today(), .(mean = mean(value)), keyby = .(dayOfYear,
compareYear)]
# final plot - adds annotations
yMin <- min(plotDT$mean)
yMax <- max(plotDT$mean)
p <- compareYearsPlot(plotDT)
p <- addLockdownDate(p)
addWeekendsDate(p)
Figure 4.2: Oxides of nitrogen levels, Southampton (daily mean)
yLab <- "Sulphour Dioxide (ug/m3)"
so2dt <- sotonAirDT[pollutant == "so2"]
Figure 5.1 shows the most recent hourly data.
recentDT <- so2dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)
p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90,
hjust = 1)) + labs(caption = paste0(myParams$lockdownCap, myParams$weekendCap))
yMax <- max(recentDT$value)
yMin <- min(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
Figure 5.1: Sulphour Dioxide levels, Southampton (hourly, recent)
Figure 5.2 shows the most recent mean daily values compared to previous years.
plotDT <- so2dt[!is.na(value) & dayOfYear <= lubridate::today(), .(mean = mean(value)), keyby = .(dayOfYear,
compareYear)]
# final plot - adds annotations
yMin <- min(plotDT$mean)
yMax <- max(plotDT$mean)
p <- compareYearsPlot(plotDT)
p <- addLockdownDate(p)
addWeekendsDate(p)
Figure 5.2: Oxides of nitrogen levels, Southampton (daily mean)
Beware seasonal trends and weather effects
yLab <- "Ozone (ug/m3)"
o3dt <- sotonAirDT[pollutant == "o3"]
Figure 6.1 shows the most recent hourly data.
recentDT <- o3dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)
p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90,
hjust = 1)) + labs(caption = paste0(myParams$lockdownCap, myParams$weekendCap))
yMax <- max(recentDT$value)
yMin <- min(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
Figure 6.1: 03 levels, Southampton (hourly, recent)
Figure 6.2 shows the most recent mean daily values compared to previous years.
plotDT <- o3dt[!is.na(value) & dayOfYear <= lubridate::today(), .(mean = mean(value)), keyby = .(dayOfYear,
compareYear)]
# final plot - adds annotations
yMin <- min(plotDT$mean)
yMax <- max(plotDT$mean)
p <- compareYearsPlot(plotDT)
p <- addLockdownDate(p)
addWeekendsDate(p)
Figure 6.2: Oxides of nitrogen levels, Southampton (daily mean)
Beware seasonal trends and weather effects
yLab <- "PM 10 (ug/m3)"
pm10dt <- sotonAirDT[pollutant == "pm10"]
Figure 7.1 shows the most recent hourly data.
recentDT <- pm10dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)
p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90,
hjust = 1)) + labs(caption = paste0(myParams$lockdownCap, myParams$weekendCap))
yMax <- max(recentDT$value)
yMin <- min(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
Figure 7.1: PM10 levels, Southampton (hourly, recent)
Figure 7.2 shows the most recent mean daily values compared to previous years.
plotDT <- pm10dt[!is.na(value) & dayOfYear <= lubridate::today(), .(mean = mean(value)), keyby = .(dayOfYear,
compareYear)]
# final plot - adds annotations
yMin <- min(plotDT$mean)
yMax <- max(plotDT$mean)
p <- compareYearsPlot(plotDT)
p <- addLockdownDate(p)
addWeekendsDate(p)
Figure 7.2: Oxides of nitrogen levels, Southampton (daily mean)
Beware seasonal trends and weather effects
yLab <- "PM 2.5 (ug/m3)"
pm25dt <- sotonAirDT[pollutant == "pm2.5"]
Figure 8.1 shows the most recent hourly data.
recentDT <- pm25dt[!is.na(value) & obsDate > myParams$recentCutDate]
p <- makeDotPlot(recentDT, xVar = "dateTimeUTC", yVar = "value", byVar = "site", yLab = yLab)
p <- p + scale_x_datetime(date_breaks = "2 day", date_labels = "%a %d %b") + theme(axis.text.x = element_text(angle = 90,
hjust = 1)) + labs(caption = paste0(myParams$lockdownCap, myParams$weekendCap, "\nNB: There is no WHO PM2.5 hourly threshold"))
yMax <- max(recentDT$value)
yMin <- min(recentDT$value)
p <- addLockdownDateTime(p)
addWeekendsDateTime(p)
Figure 8.1: PM2.5 levels, Southampton (hourly, recent)
Figure 8.2 shows the most recent mean daily values compared to previous years.
plotDT <- pm25dt[!is.na(value) & dayOfYear <= lubridate::today(), .(mean = mean(value)), keyby = .(dayOfYear,
compareYear)]
# final plot - adds annotations
yMin <- min(plotDT$mean)
yMax <- max(plotDT$mean)
p <- compareYearsPlot(plotDT)
p <- addLockdownDate(p)
addWeekendsDate(p)
Figure 8.2: Oxides of nitrogen levels, Southampton (daily mean)
Beware seasonal trends and weather effects
Several of these datasets suffer from missing data. This is visualised below.
# dt,xvar, yvar,fillVar, yLab
p <- makeTilePlot(no2dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)
p
Figure 9.1: Nitrogen Dioxide data availability and levels over time
# dt,xvar, yvar,fillVar, yLab
p <- makeTilePlot(noxdt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)
p
Figure 9.2: Oxides of nitrogen data availability and levels over time
# dt,xvar, yvar,fillVar, yLab
p <- makeTilePlot(so2dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)
p
Figure 9.3: Sulphour Dioxide data availability and levels over time
p <- makeTilePlot(o3dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)
p
Figure 9.4: Availability and level of o3 data over time
p <- makeTilePlot(pm10dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)
p
Figure 9.5: Availability and level of PM 10 data over time
p <- makeTilePlot(pm25dt, xVar = "dateTimeUTC", yVar = "site", fillVar = "value", yLab = yLab)
p
Figure 9.6: Availability and level of PM 10 data over time
Report generated using knitr in RStudio with R version 3.6.3 (2020-02-29) running on x86_64-apple-darwin15.6.0 (Darwin Kernel Version 19.4.0: Wed Mar 4 22:28:40 PST 2020; root:xnu-6153.101.6~15/RELEASE_X86_64).
t <- proc.time() - myParams$startTime
elapsed <- t[[3]]
Analysis completed in 68.049 seconds ( 1.13 minutes).
R packages used:
Arino de la Rubia, Eduardo, Hao Zhu, Shannon Ellis, Elin Waring, and Michael Quinn. 2017. Skimr: Skimr. https://github.com/ropenscilabs/skimr.
Dowle, M, A Srinivasan, T Short, S Lianoglou with contributions from R Saporta, and E Antonyan. 2015. Data.table: Extension of Data.frame. https://CRAN.R-project.org/package=data.table.
Garnier, Simon. 2018. Viridis: Default Color Maps from ’Matplotlib’. https://CRAN.R-project.org/package=viridis.
Grolemund, Garrett, and Hadley Wickham. 2011. “Dates and Times Made Easy with lubridate.” Journal of Statistical Software 40 (3): 1–25. http://www.jstatsoft.org/v40/i03/.
Müller, Kirill. 2017. Here: A Simpler Way to Find Your Files. https://CRAN.R-project.org/package=here.
Wickham, Hadley. 2009. Ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. http://ggplot2.org.
Zhu, Hao. 2018. KableExtra: Construct Complex Table with ’Kable’ and Pipe Syntax. https://CRAN.R-project.org/package=kableExtra.